package com.monkey.luffer.springboot.demo.basis.kcc.test.lianji.majiang;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author jiahong.liu
 */
public class BaseRule {

    public static boolean isHu(PlayerHand playerHand, Majiang.Card card) {
        // 把手牌重构一下：
        playerHand.putInCard(card);
        List<Integer> all = new ArrayList<>(playerHand.getAll());
        Collections.sort(all);

        // 胡的牌的个数必须是2或5或8或11或14
        if (all.size() != 2 && all.size() != 5 && all.size() != 8 && all.size() != 11 && all.size() != 14) {
            playerHand.removeCard(card);
            return false;
        }

        int [] cards = new int[all.size()];

        for (int i = 0; i < all.size(); i++) {
            cards[i] = all.get(i);
        }

        if (all.size() == 14) {
            boolean flag = true;
            // 判断是否是7对，即 0和1是一样的，且2和3是一样的
            for (int  i = 0; i < 14;) {
                if (cards[i] != cards[i + 1])  {
                    flag = false;
                    break;
                }
                i = i + 2;
            }

            if (flag) {
                return true;
            }
        }

        // 将手牌中的将取出来
        int[] js = getJiangs(cards);
        if (js.length <= 0) {
            playerHand.removeCard(card);
            return false;
        }

        for (int j : js) {
            int[] tempCards = Arrays.copyOf(cards, cards.length);
            tempCards = removeOne(tempCards, j);
            tempCards = removeOne(tempCards, j);
            Arrays.sort(tempCards);
            // 去掉所有的刻子
            tempCards = removeAllKe(tempCards);
            if (tempCards.length <= 0) {
                playerHand.removeCard(card);
                return true;
            }

            // 去掉所有的顺子
            tempCards = removeAllShun(tempCards);
            if (tempCards.length <= 0) {
                playerHand.removeCard(card);
                return true;
            }
        }
        playerHand.removeCard(card);
        return false;
    }

    /**
     * 获取牌组中所有的“将”
     *
     * @param cards 牌组
     * @return 所有的“将”组成的数组
     */
    private static int[] getJiangs(int[] cards) {
        int[] res = new int[0];
        if (null != cards && cards.length > 1) {
            for (int i = 0; i < cards.length - 1; i++) {
                if (cards[i] == cards[i + 1]) {
                    res = add(res, cards[i]);
                    i++;
                }
            }
        }
        return res;
    }

    /**
     * 去掉牌组中所有的刻子
     *
     * @param cards 牌组
     */
    private static int[] removeAllKe(int[] cards) {
        for (int i = 0; i < cards.length - 2; i++) {
            if (cards[i] == cards[i + 1] && cards[i] == cards[i + 2]) {
                cards = removeOne(cards, cards[i]);
                cards = removeOne(cards, cards[i]);
                cards = removeOne(cards, cards[i]);
            }
        }
        return cards;
    }


    /**
     * 去掉牌组中所有的顺子
     *
     * @param cards 牌组
     */
    private static int[] removeAllShun(int[] cards) {
        int[] res = Arrays.copyOf(cards, cards.length);
        for (int i = 0; i < cards.length - 2; i++) {
            if (cards[i] + 1 == cards[i + 1] && cards[i + 1] + 1 == cards[i + 2]) {
                res = removeOne(res, cards[i]);
                res = removeOne(res, cards[i + 1]);
                res = removeOne(res, cards[i + 2]);
                i += 2;
            }
        }
        return res;
    }

    /**
     * 获取去掉花色的牌的值
     *
     * @param card 原牌值
     * @return 去掉花色的牌的值
     */
    private static int getCardWithoutSuit(int card) {
        return card % 10;
    }

    /**
     * 将牌card加到牌组cards中
     *
     * @param cards 牌组
     * @param card  牌
     * @return 添加后的牌组
     */
    private static int[] add(int[] cards, int card) {
        int[] res = new int[cards.length + 1];
        System.arraycopy(cards, 0, res, 0, cards.length);
        res[res.length - 1] = card;
        return res;
    }

    /**
     * 在牌组中去掉一张牌
     *
     * @param cards 牌组
     * @param card  要去掉的牌
     * @return 去掉牌后的牌组
     */
    private static int[] removeOne(int[] cards, int card) {
        if (null == cards || cards.length <= 0) {
            return cards;
        }
        Arrays.sort(cards);
        int index = Arrays.binarySearch(cards, card);
        if (index >= 0) {
            int[] res = new int[cards.length - 1];
            int j = 0;
            for (int i = 0; i < cards.length; i++) {
                if (i != index) {
                    res[j++] = cards[i];
                }
            }
            return res;
        }
        return cards;
    }
}
